/***********************************************************************************************************************
*  OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
*  See also https://openstudio.net/license
***********************************************************************************************************************/

#include "Scale.hpp"

namespace openstudio {

std::ostream& operator<<(std::ostream& os, const Scale& s) {
  os << s.name << ", " << s.abbr << ", 10^";
  if (s.exponent < 0) {
    os << "{" << s.exponent << "}";
  } else {
    os << s.exponent;
  }
  os << " = " << s.value;

  return os;
}

bool operator==(const Scale& firstScale, const Scale& secondScale) {
  return ((firstScale.exponent == secondScale.exponent) && (firstScale.abbr == secondScale.abbr));
}

bool operator!=(const Scale& firstScale, const Scale& secondScale) {
  return !(firstScale == secondScale);
}

bool operator<(const Scale& firstScale, const Scale& secondScale) {
  return (firstScale.exponent < secondScale.exponent);
}

bool operator>(const Scale& firstScale, const Scale& secondScale) {
  return (firstScale.exponent > secondScale.exponent);
}

bool operator<=(const Scale& firstScale, const Scale& secondScale) {
  return (firstScale.exponent <= secondScale.exponent);
}

bool operator>=(const Scale& firstScale, const Scale& secondScale) {
  return (firstScale.exponent >= secondScale.exponent);
}

/** Static constant indicating that the scale was not found. To test for it,
   *  check that value == 0. */
const Scale& notDefined() {
  static const Scale ND = {"ND", "Not Defined", 0, 0.0};
  return ND;
}

/** Static constant defining SI prefix for 10^24. */
const Scale& yotta() {
  static const Scale Y = {"Y", "yotta", 24, 1.0E24};
  return Y;
}

/** Static constant defining SI prefix for 10^21. */
const Scale& zetta() {
  static const Scale Z = {"Z", "zetta", 21, 1.0E21};
  return Z;
}

/** Static constant defining SI prefix for 10^18. */
const Scale& exa() {
  static const Scale E = {"E", "exa", 18, 1.0E18};
  return E;
}

/** Static constant defining SI prefix for 10^15. */
const Scale& peta() {
  static const Scale P = {"P", "peta", 15, 1.0E15};
  return P;
}

/** Static constant defining SI prefix for 10^12. */
const Scale& tera() {
  static const Scale T = {"T", "tera", 12, 1.0E12};
  return T;
}

/** Static constant defining SI prefix for 10^9. */
const Scale& giga() {
  static const Scale G = {"G", "giga", 9, 1.0E9};
  return G;
}

/** Static constant defining SI prefix for 10^6. */
const Scale& mega() {
  static const Scale M = {"M", "mega", 6, 1.0E6};
  return M;
}

/** Static constant defining SI prefix for 10^5. */
UTILITIES_API const Scale& hectokilo() {
  static const Scale hk = {"_hk", "hectokilo", 5, 1.0E5};
  return hk;
}

/** Static constant defining SI prefix for 10^4. */
const Scale& myria() {
  static const Scale k = {"_ma", "myria", 4, 1.0E4};
  return k;
}

/** Static constant defining SI prefix for 10^3. */
const Scale& kilo() {
  static const Scale k = {"k", "kilo", 3, 1.0E3};
  return k;
}

/** Static constant defining SI prefix for 10^2. */
UTILITIES_API const Scale& hecto() {
  static const Scale h = {"_h", "hecto", 2, 1.0E2};
  return h;
}

/** Static constant defining SI prefix for 10^1. */
UTILITIES_API const Scale& deka() {
  static const Scale da = {"_da", "deka", 1, 1.0E1};
  return da;
}

/** Static constant defining no scale (1.0). */
const Scale& one() {
  static const Scale o = {"", "", 0, 1.0};
  return o;
}

/** Static constant defining SI prefix for 10^{-1} */
const Scale& deci() {
  static const Scale d = {"_d", "deci", -1, 1.0E-1};
  return d;
}

/** Static constant defining SI prefix for 10^{-2} */
const Scale& centi() {
  static const Scale c = {"c", "centi", -2, 1.0E-2};
  return c;
}

/** Static constant defining SI prefix for 10^{-3} */
const Scale& milli() {
  static const Scale m = {"m", "milli", -3, 1.0E-3};
  return m;
}

/** Static constant defining SI prefix for 10^{-4} */
const Scale& decimilli() {
  static const Scale dm = {"_dm", "decimilli", -4, 1.0E-4};
  return dm;
}

/** Static constant defining SI prefix for 10^{-5} */
const Scale& centimilli() {
  static const Scale cm = {"_cm", "centimilli", -5, 1.0E-5};
  return cm;
}

/** Static constant defining SI prefix for 10^{-6} */
const Scale& micro() {
  static const Scale mu = {"\\mu", "micro", -6, 1.0E-6};
  return mu;
}

/** Static constant defining SI prefix for 10^{-9} */
const Scale& nano() {
  static const Scale n = {"n", "nano", -9, 1.0E-9};
  return n;
}

/** Static constant defining SI prefix for 10^{-12} */
const Scale& pico() {
  static const Scale p = {"p", "pico", -12, 1.0E-12};
  return p;
}

/** Static constant defining SI prefix for 10^{-15} */
const Scale& femto() {
  static const Scale f = {"f", "femto", -15, 1.0E-15};
  return f;
}

/** Static constant defining SI prefix for 10^{-18) */
const Scale& atto() {
  static const Scale a = {"a", "atto", -18, 1.0E-18};
  return a;
}

/** Static constant defining SI prefix for 10^{-21} */
const Scale& zepto() {
  static const Scale z = {"z", "zepto", -21, 1.0E-21};
  return z;
}

/** Static constant defining SI prefix for 10^{-24} */
const Scale& yocto() {
  static const Scale y = {"y", "yocto", -24, 1.0E-24};
  return y;
}

}  // namespace openstudio
